#!usr/bin/env python3 
# -*- coding:utf8 -*-

import sys,os,json
import re
from PyQt5.QtWidgets import (QApplication,QMainWindow,QComboBox,QGridLayout,QLabel,
            QWidget,QPlainTextEdit,QLineEdit,QPushButton,QTextEdit,QMessageBox,
            QColorDialog,QAction,QMenuBar,QVBoxLayout,QHBoxLayout)
from PyQt5.Qt import Qt,QStandardItemModel,QRegExp,QFont,QTextCursor,QTextDocumentFragment,QTextDocument,QTextOption,QColor,qRgb,QIcon
from PyQt5.QtGui import QPalette

SettingFileName = "html_editor.json"

class SettingWindow(QWidget):
    def __init__(self,parent=None):
        super().__init__(parent,Qt.Window|Qt.MSWindowsFixedSizeDialogHint)        
        self.resize(300,300)
        self.setWindowTitle("设置窗口")
        vBox = QVBoxLayout()
        hBox = QHBoxLayout()        
        self.setLayout(vBox)      
        lbl = QLabel('每行一个记录，格式为"颜色名 颜色值" 颜色值必须带 # 号:') 
        vBox.addWidget(lbl)
        self.inputText = QPlainTextEdit()
        vBox.addWidget(self.inputText)
        self.btnSave = QPushButton()
        self.btnSave.resize(70,30)
        self.btnSave.setText("保存")
        self.btnSave.clicked.connect(self.onSaveHandler)
        hBox.addStretch(2)
        hBox.addWidget(self.btnSave)
        hBox.addStretch(2)
        vBox.addLayout(hBox)

        self.initSetingInfo()

    def onSaveHandler(self):
        text = str(self.inputText.toPlainText())
        if text.find("#"):            
            if not self.htmlEditorSetting:
                self.htmlEditorSetting = {}
            oldSetStr = self.htmlEditorSetting.get("uiColor","")
            if oldSetStr!=text:
                self.htmlEditorSetting['uiColor'] = text
                with open(SettingFileName,"w",encoding="utf8") as f:
                    json.dump(self.htmlEditorSetting,f,ensure_ascii=False)

        self.close()

    def initSetingInfo(self):
        self.htmlEditorSetting=None
        global SettingFileName
        if os.path.exists(SettingFileName):
            with open(SettingFileName,"r",encoding="utf8") as f:
                self.htmlEditorSetting = json.load(f)
                self.inputText.setPlainText(self.htmlEditorSetting['uiColor'])

class HtmlEditor(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowIcon(QIcon("assets/ico/logo.png"))
        self.setGeometry(350,200,700,400)
        self.setWindowTitle("Html文本编辑器")
        self.initMenu()
        self.setupUI()
        self.setWin = None

        #palette = self.palette()                
        #palette.setColor(QPalette.Window,QColor("#cccccc"))
        #palette.setColor(QPalette.Button,QColor("#00ff00")) #windows下由于涉及到样式表，所以该函数无效
        #self.setAutoFillBackground(True)
        #self.setPalette(palette)
        '''
        with open("win.qss") as f:
            style = f.read()
            self.setStyleSheet(style)
        '''
        self.setStyleSheet("QPushButton,QPlainTextEdit,QTextEdit,QComboBox{background:#cccccc;font:14px}")

    def initMenu(self):
        menu = self.menuBar()
        self.setMenu = menu.addMenu("设置(&E)") 
        self.setMenu.addAction(self.createAction("UI配色"))

    def createAction(self,text,icoUrl:str="assets/ico/logo.png"):
        act = QAction("设置(&S)",self)
        act.setShortcut("ctrl+e")
        act.setIcon(QIcon(icoUrl))
        act.setText(text)
        act.triggered.connect(self.onActionChange)
        return act 
    def onActionChange(self):
        if not self.setWin:
            self.setWin = SettingWindow(self)
            self.setWin.installEventFilter(self)
        self.setWin.show()
        
    def eventFilter(self,watch,e):
        if self.setWin and self.setWin==watch and self.setWin.isHidden():
            self.setColorData()    
        return super().eventFilter(watch, e)

    def setupUI(self):
        central = QWidget(self)        
        self.setCentralWidget(central)
        grid = QGridLayout()        
        central.setLayout(grid)
        #grid.setSpacing(10)
        grid.addWidget(self.getLbl("编辑区："),0,0)
        grid.setColumnMinimumWidth(0,self.width()*0.6) #设置第一列的最小宽度

        editRow = 4
        editCol = 10
        self.editArea = QPlainTextEdit()
        self.editArea.setWordWrapMode(QTextOption.NoWrap)
        self.editArea.resize(self.editArea.width()*2,self.editArea.height())
        grid.addWidget(self.editArea,1,0,editRow,editCol) #放在第二行第一列 占据三行三列
        #self.editArea.selectionChanged.connect(self.onEditChange)
        self.editArea.textChanged.connect(self.onEditChange)
        

        grid.addWidget(self.getLbl("UI颜色:"),1,editCol) #2行4列

        self.colorPanelBtn = QPushButton()
        self.colorPanelBtn.setText("调色板")
        self.colorPanelBtn.clicked.connect(self.onShowColorDialog)
        grid.addWidget(self.colorPanelBtn,2,editCol)
        #grid.addWidget(self.getLbl("颜色输入:"),2,editCol)

        self.colorCom = QComboBox()
        grid.addWidget(self.colorCom,1,editCol+1)
        f = QFont("宋体",12)
        #self.colorCom.setFont(f)        
        self.colorCom.activated[str].connect(self.onSelectColor)
        self.setColorData()
        
        self.colorInput = QLineEdit()
        grid.addWidget(self.colorInput,2,editCol+1)

        self.excBtn = QPushButton()
        self.excBtn.setText("执 行")
        grid.addWidget(self.excBtn,2,editCol+2)
        self.excBtn.clicked.connect(self.onClickExc)
        self.excBtn.setToolTip("如果输入颜色使用输入，否则使用当前颜色列表选中的颜色")

        self.clearBtn = QPushButton()
        self.clearBtn.setText("清空输入")
        grid.addWidget(self.clearBtn,3,editCol+1)
        self.clearBtn.clicked.connect(self.clearEditFmt)

        self.clearFmtBtn = QPushButton()
        self.clearFmtBtn.setText("清除格式")
        grid.addWidget(self.clearFmtBtn,3,editCol)
        self.clearFmtBtn.clicked.connect(self.clearEditFmt)
        self.clearFmtBtn.setToolTip("有选中清除选中的文本格式，没有选中清除所有格式")

        grid.addWidget(self.getLbl("预览区："),editRow+1,0)

        self.viewArea = QTextEdit()
        self.viewArea.setReadOnly(True)
        #self.viewArea.setEnabled(False)
        grid.addWidget(self.viewArea,editRow+2,0,editRow,editCol) #放在第二行第一列 占据三行三列
    
    def setColorData(self):
        self.colorData = []
        global SettingFileName
        if os.path.exists(SettingFileName):
            with open(SettingFileName,"r",encoding="utf8") as f:
                obj = json.load(f)
                colorStr = str(obj['uiColor'])
                self.colorData = [ x.strip() for x in colorStr.split("\n") if x.strip()!=""]

        self.colorCom.clear()
        self.colorCom.addItems(self.colorData)

    def getLbl(self,text:str):
        lbl = QLabel()
        lbl.setText(text)
        return lbl

    def onShowColorDialog(self):
        qColor = QColor(QColorDialog.getColor())        
        if qColor.isValid():
            clr = hex(qColor.rgba()) # rgba、rgb函数得到的都是arbg值
            clr = clr[4:]
            self.colorInput.setText(clr)
            self.setEditColor(clr)

    def onClickExc(self,e):
        clr = self.colorInput.text()
        clr = clr.replace("#","")
        #print("self.colorCom.currentData",self.colorCom.currentText())
        if len(clr)==6:
            self.setEditColor(clr)
        else:
            self.onSelectColor(self.colorCom.currentText())
            #QMessageBox.information(self,"提示","请输入正确的16进制颜色值")
        

    def clearEditFmt(self):
        sender = self.sender()
        obj = re.compile(r"<.*?>")
        if sender==self.clearFmtBtn:
            oldText = str(self.editArea.toPlainText())
            selectText,cursor = self.getSelection()
            if selectText:
                stPos = cursor.selectionStart()
                endPos = cursor.selectionEnd()
                selectText = obj.sub("",selectText)      
                newText = oldText[0:stPos]+selectText+oldText[endPos:]
                self.editArea.setPlainText(newText)
            else:     
                reply = QMessageBox.question(self,"提示","是否清除所有格式?",QMessageBox.Ok|QMessageBox.Cancel)
                if reply==QMessageBox.Ok:                    
                    oldText = obj.sub("",oldText)        
                    self.editArea.setPlainText(oldText)
                    self.viewArea.setText(oldText)

        elif sender==self.clearBtn:
            self.editArea.clear()

    def onSelectColor(self,text):
        clr = text.split("#")[1]
        self.setEditColor(clr)

    def setEditColor(self,color:str):
        oldText = self.editArea.toPlainText()
        space = re.compile(r"\s")
        mobj = space.match(oldText)
        
        selectText,cursor = self.getSelection()
        if selectText:
            stPos = cursor.selectionStart()
            endPos = cursor.selectionEnd()        
            color = color.strip()
            clrTag0= '<font color="#{0}" >'.format(color)
            clrTag1 = '</font>'
            newText = oldText[0:stPos]+clrTag0+selectText+clrTag1+oldText[endPos:]
            
            self.editArea.setPlainText(newText)
            newText = newText.replace("\n","<br>")
            self.viewArea.setText(newText)

    def getSelection(self):
        self.editArea.setFocus()
        cursor = QTextCursor(self.editArea.textCursor())        
        selection = QTextDocumentFragment(cursor.selection())
        selectText = selection.toPlainText()
        return selectText,cursor

    def onEditChange(self):
        oldText = self.editArea.toPlainText()
        newText = oldText.replace("\n","<br>")
        self.viewArea.setText(newText)
        
if __name__=="__main__":
    app = QApplication(sys.argv)
    win = HtmlEditor()
    win.show()
    sys.exit(app.exec())

